const fireBallSkill = "FireBall"

let hasShoot = false;

class Player extends MyGameObject {
    constructor(playground, x, y, radius, color, speed, isMe) {
        super();

        this.x = x;
        this.y = y;
        this.vx = 0;
        this.vy = 0;
        this.playground = playground;
        this.ctx = playground.gameMap.ctx;
        this.radius = radius;
        this.color = color;
        this.speed = speed * 0.2;
        this.isMe = isMe;
        this.moveLength = 0;
        this.eps = 0.01;

        this.damageX = 0;
        this.damageY = 0;
        this.damageSpeed = 0;
        this.friction = 0.95;
        this.curSkill = null;
        this.k = 15000;
        if (isMe) {
            this.img = new Image()
            this.img.src = this.playground.root.settings.photo
        }
    }

    add_listening_events() {
        let outer = this;
        this.playground.gameMap.$canvas.on("contextmenu", function () {
            return false;
        })
        this.playground.gameMap.$canvas.mousedown(function (e) {
            if (e.which === 1) {
                if (outer.curSkill === fireBallSkill) {
                    outer.shootFireBall(e.clientX / outer.playground.scale, e.clientY / outer.playground.scale)
                    outer.curSkill = null
                    return false
                }
                if (outer.curSkill === null) {
                    outer.moveTo(e.clientX / outer.playground.scale, e.clientY / outer.playground.scale)
                    return false
                }
            }
        })
        $(window).keydown(function (e) {
            if (e.keyCode === 81) {
                outer.curSkill = fireBallSkill;
                return false;
            }
        })
    }

    shootFireBall(tx, ty) {
        let x = this.x, y = this.y;
        let radius = 0.01;
        let angle = Math.atan2(ty - this.y, tx - this.x);
        let vx = Math.cos(angle), vy = Math.sin(angle);
        let color = "orange";
        let speed = 1;
        let moveLength = 1.5;
        new FireBall(this.playground, this, x, y, radius, vx, vy, color, speed, moveLength, 0.01);
    }

    // 烟花效果
    bomb() {
        for (let i = 0; i < 10 + Math.random() * 5; i++) {
            let x = this.x;
            let y = this.y;
            let radius = this.radius * Math.random() * 0.1;
            let angle = Math.PI * 2 * Math.random();
            let vx = Math.cos(angle);
            let vy = Math.sin(angle);
            let color = this.color;
            let speed = this.speed * 10;
            let moveLength = this.radius * Math.random() * 10;
            new Particle(this.playground, x, y, radius, speed, vx, vy, moveLength, color);
        }
    }

    beAttacked(angle, damage) {
        this.radius -= damage;
        if (!this.isMe) {
            this.speed *= 0.8;
        } else {
            this.speed *= 1.2;
        }
        this.bomb();

        if (this.radius < this.eps) {
            this.destroy();
            return false;
        }

        this.damageX = Math.cos(angle);
        this.damageY = Math.sin(angle);
        this.damageSpeed = damage * 150;
    }


    getDist(x1, y1, x2, y2) {
        let dx = (x1 - x2);
        let dy = (y1 - y2);
        return Math.sqrt(dx * dx + dy * dy)
    }

    moveTo(tx, ty) {
        this.moveLength = this.getDist(this.x, this.y, tx, ty);
        let angle = Math.atan2(ty - this.y, tx - this.x);
        this.vx = Math.cos(angle);
        this.vy = Math.sin(angle);
    }

    start() {
        if (this.isMe) {
            this.add_listening_events();
        } else {
            let tx = Math.random() * this.playground.width / this.playground.scale;
            let ty = Math.random() * this.playground.height / this.playground.scale;

            this.moveTo(tx, ty);
        }
    }

    update_move() { // 更新玩家移动
        if (this.damageSpeed > this.eps) {
            // 受到攻击后瞬移
            this.vx = this.vy = 0;
            this.moveLength = 0;
            this.x += this.damageX * this.damageSpeed * this.timeDelta / 1000;
            this.y += this.damageY * this.damageSpeed * this.timeDelta / 1000;
            this.damageSpeed *= this.friction;
        } else {
            if (this.moveLength < this.eps) {
                this.moveLength = 0;
                this.vx = this.vy = 0;
                if (!this.isMe) {
                    let tx = Math.random() * this.playground.width / this.playground.scale;
                    let ty = Math.random() * this.playground.height / this.playground.scale;

                    this.moveTo(tx, ty);
                }
            } else {
                let moved = Math.min(this.moveLength, this.speed * this.timeDelta / 1000)
                this.x += this.vx * moved;
                this.y += this.vy * moved;
                this.moveLength -= moved;
            }
        }
    }

    update() {
        this.update_move()

        // 玩家之间碰撞反弹
        for (let i = 0; i < this.playground.players.length; i++) {
            let player = this.playground.players[i];
            if (player === this) {
                continue;
            }
            let dist = this.getDist(this.x, this.y, player.x, player.y);
            if (dist < (this.radius + player.radius)) {
                this.getTouched(player);
                player.getTouched(this);
            }
        }

        //
        for (let i = 0; i < this.playground.players.length; i++) {
            let player = this.playground.players[i];
            let players = this.playground.players;
            if (player.isMe) {
                continue;
            }
            if (this.k !== 1000) {
                this.k--;
            }
            if (Math.random() * this.k < 1) {
                player.shootFireBall(players[0].x, players[0].y);
            }
        }

        this.render();
    }

    getTouched(player) {
        this.bomb();
        let angle = Math.atan2(player.y - this.y, player.x - this.x);
        if (player.isMe && hasShoot) {
            player.beAttacked(angle, player.radius * 0.2);
            return false;
        }
        this.vx = -Math.cos(angle) + Math.random() * 0.05;
        this.vy = -Math.sin(angle) + Math.random() * 0.05;
    }

    destroy() {
        super.destroy();
        for (let i = 0; i < this.playground.players.length; i++) {
            let player = this.playground.players[i];
            if (player === this) {
                this.playground.players.splice(i, 1);
                break;
            }
        }
    }

    render() {
        let scale = this.playground.scale
        if (this.isMe) {
            this.img.src = this.playground.root.settings.photo
            this.ctx.save()
            this.ctx.beginPath()
            this.ctx.arc(this.x * scale, this.y * scale, this.radius * scale, 0, Math.PI * 2, false)
            this.ctx.clip()
            this.ctx.drawImage(this.img, (this.x - this.radius) * scale, (this.y - this.radius) * scale, this.radius * 2 * scale, this.radius * 2 * scale)
            this.ctx.restore()
        } else {
            this.ctx.beginPath();
            this.ctx.arc(this.x * scale, this.y * scale, this.radius * scale, 0, Math.PI * 2, false);
            this.ctx.fillStyle = this.color;
            this.ctx.fill();
        }
    }
}